from cv2 import findContours, boundingRect
from cv2 import threshold, copyMakeBorder
from cv2 import imread , cvtColor , COLOR_BGR2RGB
from cv2 import RETR_EXTERNAL, CHAIN_APPROX_NONE
from cv2 import THRESH_BINARY, THRESH_BINARY_INV
from cv2 import BORDER_CONSTANT
from matplotlib import pyplot
from numpy import ndarray

__all__ = [
    "Border2d",
    "findBorderContours",
    "show_plt",
    "binarization",
    "tosquare",
]


class Border2d:
    """边界类"""

    def __init__(self, x, y, hight, weight):
        self.x: int = x
        self.y: int = y
        self.hight: int = hight
        self.weight: int = weight
        self.begin: tuple = (x, y)
        self.end: tuple = (x + weight, y + hight)

    def slice(self):
        """用于切片"""
        return slice(self.y, self.y + self.hight), slice(self.x, self.x + self.weight)

    def corner(self, horizon: str, vertical: str):
        """四个角落的坐标\n
        left|right&up|down"""
        if horizon.lower() == "left":
            if vertical.lower() == "up":
                return self.x, self.y
            elif vertical.lower() == "down":
                return self.x + self.hight, self.y
        elif horizon.lower() == "right":
            if vertical.lower() == "up":
                return self.x, self.y + self.weight
            elif vertical.lower() == "down":
                return self.x + self.hight, self.y + self.weight
        return

    def shape(self):
        """长宽"""
        return self.hight, self.weight

    def diagonal(self):
        """对角线"""
        return self.begin, self.end


def findBorderContours(pic: ndarray):
    """寻找到图中物体最外边的边界"""
    contours, _ = findContours(pic, RETR_EXTERNAL, CHAIN_APPROX_NONE)
    for contour in contours:
        x, y, w, h = boundingRect(contour)
        yield Border2d(x, y, h, w)


def binarization(img: ndarray, negative: bool = False) -> ndarray:
    """图片二值化\n
    negative负片"""
    ttype = THRESH_BINARY_INV if negative else THRESH_BINARY
    _, pic = threshold(img, 127, 255, type=ttype)
    return pic


def tosquare(pic: ndarray) -> ndarray:
    """把长方形图片填充成正方形"""
    ep = (max(pic.shape) - min(pic.shape)) >> 1
    ep2 = max(pic.shape) >> 2
    return copyMakeBorder(pic, ep2, ep2, ep + ep2, ep + ep2, BORDER_CONSTANT)


def imread_cv(fp: str) -> ndarray:
    """读入RGB图片，用opencv2"""
    return cvtColor(imread(fp), COLOR_BGR2RGB)


def show_plt(pic: ndarray, title: str = '', axis: str = "off") -> None:
    """展示图片，用matplotlib.pyplot"""
    pyplot.imshow(pic, interpolation="bilinear")
    pyplot.title(title)
    pyplot.axis(axis)
    pyplot.show()
